package com.excilys.capicsoubank.services.impl;

import java.util.List;
import java.util.Locale;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.excilys.capicsoubank.dao.TransactionDao;
import com.excilys.capicsoubank.entities.Account;
import com.excilys.capicsoubank.entities.Transaction;
import com.excilys.capicsoubank.entities.TransactionType;
import com.excilys.capicsoubank.services.AccountService;
import com.excilys.capicsoubank.services.XlsDownloadService;
import com.excilys.capicsoubank.util.DateUtil;

/**
 * Implémentation de télécharger au format excel des trucs.
 * 
 * @author "Grégory Coutant"
 * 
 */
@Service
@Transactional(readOnly = true)
public class XlsDownloadServiceImpl implements XlsDownloadService {

	private static final short DATE_FORMAT_INDEX = 0x16;
	private static final short CURRENCY_FORMAT_INDEX = 0x28;

	@Autowired
	private TransactionDao transactionDao;

	@Autowired
	private AccountService accountService;

	@Autowired
	private MessageSource messageSource;

	private final DateTimeFormatter monthFormatter = new DateTimeFormatterBuilder()
			.appendMonthOfYearText().appendLiteral(" ").appendYear(4, 4)
			.toFormatter();

	@Override
	public HSSFWorkbook downloadXLS(Integer accountId, int year, int month,
			Locale locale) {

		Assert.notNull(accountId);

		Account account = accountService.getAccountById(accountId);

		DateTime startDate = DateUtil.firstDayOfMonth(year, month);
		DateTime endDate = DateUtil.lastDayOfMonth(year, month);

		List<Transaction> transactions = transactionDao
				.getTransactionByAccountByYearByMonthByType(account, startDate,
						endDate, TransactionType.ALL);

		return buildExcel(account, transactions, year, month, locale);
	}

	/**
	 * Créé le fichier excel.
	 * 
	 * @param account
	 *            Le compte affiché
	 * @param transactions
	 *            La liste des transactions
	 * @param year
	 *            Année voulue
	 * @param month
	 *            Mois voulu
	 * @param locale
	 *            La langue voulue
	 * @return Le fichier excel
	 */

	private HSSFWorkbook buildExcel(Account account,
			List<Transaction> transactions, int year, int month, Locale locale) {

		HSSFWorkbook workbook = new HSSFWorkbook();
		workbook.createSheet(messageSource.getMessage("title", null, locale));

		HSSFSheet worksheet = workbook.getSheetAt(0);

		int startRowIndex = 0;

		worksheet.setColumnWidth(0, 5000);
		worksheet.setColumnWidth(1, 12000);
		worksheet.setColumnWidth(2, 6000);
		worksheet.setColumnWidth(3, 6000);

		// Title
		Row row = worksheet.createRow(startRowIndex++);
		row.createCell(0).setCellValue(
				messageSource.getMessage("title.transactions", null, locale));

		Object[] params = { account.getAccountId() };
		row.createCell(1).setCellValue(
				messageSource.getMessage("title.account", params, locale));

		DateMidnight monthDate = new DateMidnight(year, month, 1);
		params[0] = monthDate.toString(monthFormatter.withLocale(locale));
		row.createCell(2).setCellValue(
				messageSource.getMessage("title.month", params, locale));

		// Header
		startRowIndex++;

		row = worksheet.createRow(startRowIndex++);

		row.createCell(0).setCellValue(
				messageSource.getMessage("title.type", null, locale));

		row.createCell(1).setCellValue(
				messageSource.getMessage("title.label", null, locale));

		row.createCell(2).setCellValue(
				messageSource.getMessage("title.amount", null, locale));

		row.createCell(3).setCellValue(
				messageSource.getMessage("title.date", null, locale));

		// filling

		CellStyle cellStyleDate = workbook.createCellStyle();
		cellStyleDate.setDataFormat(DATE_FORMAT_INDEX);

		CellStyle cellStyleCurrency = workbook.createCellStyle();
		cellStyleCurrency.setDataFormat(CURRENCY_FORMAT_INDEX);

		if (transactions.size() == 0) {
			row = worksheet.createRow(startRowIndex);

			row.createCell(1).setCellValue(
					messageSource.getMessage("none", null, locale));

			return workbook;
		}

		Cell cell;
		for (Transaction transaction : transactions) {

			row = worksheet.createRow(startRowIndex++);

			row.createCell(0).setCellValue(
					transaction.getTransactionType().toString());

			row.createCell(1).setCellValue(transaction.getLabel());

			cell = row.createCell(2);
			cell.setCellValue(transaction.getAmount() / 100.0);
			cell.setCellStyle(cellStyleCurrency);

			cell = row.createCell(3);
			cell.setCellValue(transaction.getDate().toCalendar(locale));
			cell.setCellStyle(cellStyleDate);
		}

		return workbook;
	}

}
